App.require(["canvasTool", "strlayer"], function (canvasTool, strlayer) {
    var app = App.getCurrent();

    app.defineLayer("str-canvas", {
        render: function (next) {
            this.initProperty();
            this.fetch("./index.html", function (text) {
                next(this.renderHTML(text));
            })
        },
        initProperty: function () {
            var ratio = window.devicePixelRatio;
            // this.data.styleStr = "width: " + this.width + "px; height: " + this.height + "px";
            this.data.cwidth = this.width * ratio;
            this.data.cheight = this.height * ratio;
            this.resource = new strlayer.Resource();
            this.gradient = new strlayer.Gradient();
            this.pattern = new strlayer.Pattern(this);
            this.marker = new strlayer.Marker(this);
            this.animation = new strlayer.Animation(this);
        },
        addChangeProperty: function (obj) {
            this.animation.addProperty(obj);
        },
        resetRadialGradientById: function (obj) {
            this.gradient.resetRadial(obj);
        },
        resetLinearGradientById: function (obj) {
            this.gradient.resetLinear(obj);
        },
        resetPatternById: function (obj) {
            this.pattern.reset(obj);
        },
        resetMarkerById: function (id) {
            this.marker.reset(id);
        },
        getUseGradients: function (id) {
            return this.gradient.getUseById(id);
        },
        getUsePatterns: function (id) {
            return this.pattern.getUseById(id);
        },
        getUseMarkers: function (id) {
            return this.marker.getUseById(id);
        },
        removeFillOrStrokeByValue: function (value, target) {
            var firstChart = value.slice(0, 1);
            if (firstChart === "#") this.gradient.remove(value.slice(1), target);
            else if (firstChart === "$")  this.pattern.remove(value.slice(1), target);
        },
        removeMarkerByValue: function (value, target) {
            if (value.indexOf("#") === 1) this.marker.remove(value.slice(1), target);
        },
        getDomObj: function () {
            this.attachDom("canvas", "canvas")
                .attachEvent("canvas", "canvasclick", this.clickHandler, false)
                .attachEvent("canvas", "mousedown", this.mousedownHandler, false)
                .attachEvent("canvas", "mouseup", this.mouseUpHandler, false)
                .attachEvent("canvas", "removecomponent", this.removeComponentHandler, false)
                .attachEvent("canvas", "addcomponent", this.removeComponentHandler, false)
                .attachEvent("canvas", "mouseleave", this.mouseMoveHandler, false)
                .attachEvent("canvas", "mousemove", this.mouseMoveHandler, false);
        },
        loadImages: function (list, bk) {
            var resource = this.resource;
            for (var i = 0; i < list.length; i++) {
                resource.addImage(list[i]);
            }
            resource.loadComplete(bk);
        },
        mouseUpHandler: function (ev) {
            var x = ev.clientX, y = ev.clientY;
            if (x == this.data.dx && y == this.data.dy) {
                this.dispatchCustomEvent("canvasclick", {
                    clientX: x, clientY: y, target: this.domList.canvas,
                    stopPropagation: function () { ev.stopPropagation();},
                    preventDefault: function () { ev.preventDefault(); }
                })
            }
        },
        removeComponentHandler: function (ev) {
            this.animation.removeTarget(ev.target);
            this.addChangeProperty({type: "instance", target: this});
        },
        mouseMoveHandler: function (ev) {
            var x = ev.clientX, y = ev.clientY, canvas = this.domList.canvas, bounds = canvas.getBoundingClientRect();
            this.moveTravaseTree({
                clientX: (x - bounds.left) * canvas.width / bounds.width,
                clientY: (y - bounds.top) * canvas.height / bounds.height,
                stopPropagation: function () { ev.stopPropagation();},
                preventDefault: function () { ev.preventDefault(); }
            }, this.data.ctx, window.devicePixelRatio);
        },
        clickHandler: function (ev) {
            ev = ev.detail;
            var x = ev.clientX, y = ev.clientY, canvas = this.domList.canvas, bounds = canvas.getBoundingClientRect();
            this.clickTravaseTree({
                clientX: (x - bounds.left) * canvas.width / bounds.width,
                clientY: (y - bounds.top) * canvas.height / bounds.height,
                stopPropagation: function () { ev.stopPropagation();},
                preventDefault: function () { ev.preventDefault(); }
            }, this.data.ctx, window.devicePixelRatio);
        },
        mousedownHandler: function (ev) {
            var x = ev.clientX, y = ev.clientY, canvas = this.domList.canvas, bounds = canvas.getBoundingClientRect();
            this.data.dx = x;
            this.data.dy = y;
            this.mousedownTravaseTree({
                clientX: (x - bounds.left) * canvas.width / bounds.width,
                clientY: (y - bounds.top) * canvas.height / bounds.height,
                stopPropagation: function () { ev.stopPropagation();},
                preventDefault: function () { ev.preventDefault(); }
            }, this.data.ctx, window.devicePixelRatio);
        },
        init: function () {
            console.log(this.components);
            var ctx = this.data.ctx = this.domList.canvas.getContext("2d");
            this.gradient.init(ctx);
            this.pattern.init(ctx);
            this.resource.loadComplete(function () {
                if (!this.animation.init()) {
                    this.addChangeProperty({type: "instance", target: this});
                }
            }.bind(this))
        },
        draw: function () {
            var that = this;
            if (!this.resource.isComplete()) {
                this.resource.loadComplete(function () {
                    that.addChangeProperty({type: "instance", target: that });
                }.bind(this));
            }
            else {
                var ctx = this.data.ctx, ratio = window.devicePixelRatio;
                if (!ctx) return;
                ctx.font = this.computeFont("10px Arial", ratio);
                ctx.clearRect(0, 0, ctx.canvas.width, ctx.canvas.height);
                var components = this.components;
                for (var i = 0; i < components.length; i++) {
                    var com = components[i];
                    if (typeof com.draw === "function") com.draw(this.data.ctx, ratio);
                }
            }
        },
        dispose: function () {
            this.pattern.dispose();
            this.gradient.dispose();
            this.data.ctx = null;
        },
        _destroy: function () {
            this.resource.destroy();
            this.gradient.destroy();
            this.pattern.destroy();
            this.marker.destroy();
            this.animation.destroy();
        },
        get width() {
            return this.getValue("width");
        },
        set width(value) {
            this.setValue("width", value);
        },
        get height() {
            return this.getValue("height");
        },
        set height(value) {
            this.setValue("height", value);
        }
    })
})